use std::{collections::HashMap, convert::Infallible, sync::Arc};

use apikit::rpc::{DutyClient, ServerAddressManager};
use axum::{
    extract::{FromRef, FromRequestParts, State},
    http::request::Parts,
};
use reqwest::Client;
use tracing::warn;

#[derive(Clone)]
pub struct ServerRegistry {
    pub servers: Arc<HashMap<String, String>>,
}

impl ServerAddressManager for ServerRegistry {
    fn get_server_addr(&self, name: &str) -> &str {
        let server_addr = self.servers.get(name);
        match server_addr {
            Some(addr) => addr.as_str(),
            None => {
                warn!("未配置服务[{name}]地址");
                ""
            },
        }
    }
}

pub struct RpcClient<C: DutyClient<Client, ServerRegistry>>(pub C);

impl<C, S> FromRequestParts<S> for RpcClient<C>
where
    C: DutyClient<Client, ServerRegistry>,
    S: Send + Sync,
    Client: FromRef<S>,
    ServerRegistry: FromRef<S>,
{
    type Rejection = Infallible;

    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
        let client: State<Client> = State::from_request_parts(parts, state).await?;
        let registry: State<ServerRegistry> = State::from_request_parts(parts, state).await?;
        let duty_client = <C as DutyClient<Client, ServerRegistry>>::new(client.0, registry.0);
        Ok(RpcClient(duty_client))
    }
}


